# -*- coding: utf-8 -*-
"""
@Time ： 2025/5/23 17:27
@Auth ： 九问
@File ：extract_utils.py
@IDE ：PyCharm
@Email : 2750826557@qq.com
"""
import re
from typing import Any
import jsonpath
import yaml
from pathlib import Path
from hotload.debug_talk import DebugTalk


class ExtractUtils:
    """数据提取工具类（加载时固定读取extract.yaml）"""

    def __init__(self):
        self.all_extracted = {}  # 临时存储提取的数据
        self.extract_file = Path("extract.yaml")  # 固定文件路径

    def extract(self, res, name: str, expr: str) -> None:
        """从响应中提取数据到内存"""
        try:
            json_data = res.json()
            value = jsonpath.jsonpath(json_data, expr)
            if value:
                self.all_extracted[name] = value[0]
        except Exception:
            pass

    @staticmethod
    def change(data: dict):
        """yaml 表达式替换为extract.yaml提取的值"""
        data_str = yaml.safe_dump(data)  # dict->str
        # new_data_str = Template(data_str).safe_substitute(read_yaml())
        new_data_str = ExtractUtils.hot_load_replace(data_str)
        data_dict = yaml.safe_load(new_data_str)
        return data_dict

    def save_to_yaml(self) -> None:
        """将内存中的数据保存到extract.yaml"""
        if self.all_extracted:
            with open(self.extract_file, "w", encoding="utf-8") as f:
                yaml.safe_dump(self.all_extracted, f)

    @classmethod
    def get(cls, key: str) -> Any:
        """直接从extract.yaml获取值"""
        try:
            with open("extract.yaml", "r", encoding="utf-8") as f:
                data = yaml.safe_load(f) or {}
            return data.get(key)
        except FileNotFoundError:
            return None

    @staticmethod
    def hot_load_replace(data_str: str):
        pattern = "\\$\\{(.*?)\\((.*?)\\)\\}"  # ${函数名(参数)}
        func_li = re.findall(pattern, data_str)  # [('get_random_num', ''), ('md5', 'pwd'),('add','1,2')]
        for f in func_li:
            old_value = "${%s(%s)}" % (f[0], f[1])
            if f[1]:  # 有参数
                value = getattr(DebugTalk, f[0])(*f[1].split(","))
            else:
                value = getattr(DebugTalk, f[0])()
            if isinstance(value, str) and value.isdigit():  # 数字字符串
                value = f"'{value}'"
            data_str = data_str.replace(old_value, str(value))
        return data_str


if __name__ == '__main__':
    request_data = {
        "method": "get",
        "user": "${id}",
        "phone": "${phone}",
        "token": "${read_yaml_key(token)}",
        "pwd": "${md5()}",
        "code": "${get_random_num()}",
        "add": "${add(1,2)}",
        "num": "${read_yaml_key(number)}"
    }
    # request_data_str = yaml.safe_dump(request_data)
    # sub_data_str = Template(request_data_str).safe_substitute(
    #     {"id": 1, "phone": "18302843233", "token": "effewfwef"})
    # print(sub_data_str)
    # print(yaml.safe_load(sub_data_str))  # {'method': 'get', 'phone': 18302843233, 'token': 'effewfwef', 'user':
    # 1}这种方式会将数字字符串意外替换为数字类型
    # sub_data_str2 = ExtractUtils.hot_load_replace(request_data_str)
    # print(sub_data_str2)
    request_data = ExtractUtils.change(request_data)
    print(request_data)

